<template>
  <div>
    <!-- 导航栏 -->
    <!-- 做路由跳转：跳转到用户页（其实就是返回） -->
    <!-- $router.back() 意思就是返回上一页 -->
    <van-nav-bar title="编辑资料" left-arrow @click-left="$router.back()" />

    <!-- 头像区域 -->
    <div class="avatar-box">
      <van-image round class="avatar" fit="cover" :src="info.photo" />

      <van-uploader class="pic-uploader" :after-read="afterRead" />
    </div>

    <!-- 资料区域 -->
    <van-cell-group>
      <van-cell @click="changeName" title="名称" :value="info.name" is-link />
      <!-- 我们的接口性别返回1和0，用1代表男，用0代表女 -->
      <!-- 1其实就是true,0就是false -->
      <van-cell
        @click="genderShow = true"
        title="性别"
        :value="info.gender ? '男' : '女'"
        is-link
      />
      <van-cell
        @click="clickShowBirth"
        title="生日"
        :value="info.birthday"
        is-link
      />
    </van-cell-group>

    <!-- 弹出框 -- 修改名字 -->
    <!-- v-model用来控制这个弹出框是否显示 -->
    <van-dialog
      @confirm="saveName"
      v-model="nameShow"
      title="修改名字"
      show-cancel-button
    >
      <van-field
        ref="nameInp"
        class="nameField"
        v-model="editName"
        placeholder="请输入用户名"
      />
    </van-dialog>

    <!-- 弹出层 - 修改性别 -->
    <!-- v-model用来控制弹出层的显示 -->
    <van-popup v-model="genderShow" position="bottom" class="pop">
      <van-nav-bar
        title="修改性别"
        left-text="取消"
        @click-left="genderShow = false"
      />
      <van-cell @click="changeGender(1)" title="男" is-link />
      <van-cell @click="changeGender(0)" title="女" is-link />
    </van-popup>

    <!-- 弹出生日选择的区域 -->
    <van-popup v-model="birthShow" position="bottom" class="popBirth">
      <!-- 生日选择器 -->
      <van-datetime-picker
        v-model="currentDate"
        @confirm="changeBirth"
        @cancel="birthShow = false"
        type="date"
        title="选择年月日"
        :min-date="minDate"
        :max-date="maxDate"
      />
    </van-popup>

    <!-- 图片裁剪容器 -->
    <div class="crop-box" v-if="cropShow">
      <vueCropper
        ref="cropper"
        :img="cropImg"
        autoCrop
        autoCropWidth="150"
        autoCropHeight="150"
      ></vueCropper>

      <!-- 按钮 -->
      <van-button @click="doCrop" type="primary">裁剪</van-button>
      <van-button @click="cropShow=false" type="primary">取消</van-button>
    </div>
  </div>
</template>

<script>
import { editUserInfoAPI, changePhotoAPI } from "@/api";
import moment from "moment";
// 导入裁剪插件
import { VueCropper } from "vue-cropper";
export default {
  // 把裁剪功能注册成局部的组件
  components: {
    VueCropper,
  },
  data() {
    return {
      nameShow: false,
      // 用来跟修改名字输入框双向绑定的变量
      editName: "",
      genderShow: false,
      currentDate: new Date(),
      // new Date就是获取当前时间，那也就是今天
      maxDate: new Date(),
      minDate: new Date("1960-1-1"),
      birthShow: false,
      // 用来控制裁剪容器的显示和隐藏
      cropShow: false,
      cropImg: "",
    };
  },
  methods: {
    // 点击cell显示弹出框的事件
    changeName() {
      // 1. 显示出对话框（会立即显示对话框吗？不会）
      // 这里仅仅只是数据发生了变化，但是dom还没有得到更新
      // 它要等本次同步代码都执行完了，才会去渲染dom
      this.nameShow = true;
      // 2. 让对话框里的输入框显示当前的用户名
      this.editName = this.info.name;
      // 3. 让输入框获得焦点
      // console.log(this.$refs.nameInp) // undefined，因为dom还没渲染出来这个对话框
      // 如何才能等到dom更新呢？？两个方法：写到updated钩子里（不推荐）
      // 推荐：$nextTick。这是一个等下次dom更新就会调用的回调函数
      this.$nextTick(() => {
        this.$refs.nameInp.focus();
      });
    },

    // 点击修改名字确认的事件
    async saveName() {
      // 发请求去修改名字
      await editUserInfoAPI({
        name: this.editName,
      });

      // 发完请求后就把本地的数据做一个更新
      // 本地数据存在vuex里，所以要通过vuex访问
      this.$store.commit("setUserInfo", {
        // 还得把以前的所有属性也放到这个对象里
        ...this.info,
        // 只是让name变成新修改的数据
        name: this.editName,
      });
    },

    // 点击男或女触发的事件
    async changeGender(gender) {
      // 发请求去修改用户性别
      await editUserInfoAPI({
        gender,
      });

      // 修改到vuex里
      this.$store.commit("setUserInfo", {
        ...this.info,
        gender,
      });

      // 弹出层隐藏
      this.genderShow = false;
    },

    // 点击生日cell触发的事件
    clickShowBirth() {
      this.birthShow = true;
      // 把当前用户的生日给生日选择器
      this.currentDate = new Date(this.info.birthday);
    },

    // 修改生日的确认事件
    async changeBirth() {
      // 发请求给服务器去修改
      // 因为服务器要的事字符串，而currentDate是一个日期对象
      // 所以这里需要把日期对象转成字符串
      const birthday = moment(this.currentDate).format("YYYY-MM-DD");
      await editUserInfoAPI({
        birthday,
      });

      // 修改到vuex里
      this.$store.commit("setUserInfo", {
        ...this.info,
        birthday,
      });

      // 弹出层隐藏
      this.birthShow = false;
    },

    // 选择完文件触发的函数
    // 参数file就是选择的这个文件的信息
    // 两个重要的属性：file.content：会得到这个文件的base64编码
    // file.file 会得到这个文件对象（文件对象是用来可以做上传）
    afterRead(file) {
      // // 此时可以自行将文件上传至服务器
      // console.log("选择完了", file);
      // 显示出裁剪容器
      this.cropShow = true;
      // 把我们选中的图片，交给裁剪插件去显示
      this.cropImg = file.content;
    },

    // 裁剪按钮的点击事件
    doCrop() {

      // 调用插件的裁剪功能得到裁剪结果
      this.$refs.cropper.getCropBlob(async (data) => {
        // 这个参数data就是得到的裁剪后的blob对象
        // 发请求传递给服务器
        // 调用这个接口要上传图片，ajax上传图片能直接传图片吗？？
        // 不能，那要怎么上传图片，ajax要像能上传一切文件，都必须要用到一个对象
        // 这个对象叫FormData，利用FormData才能使用ajax上传文件
        let fm = new FormData() // 好多同学容易写成 FromData（错！错！错！）
        // 把图片对象加到fm对象里
        fm.append('photo', data)

        // 调用接口传递fm对象（上传图片了）
        let res = await changePhotoAPI(fm)
        // 上传成功后，更新到vuex
        this.$store.commit('setUserInfo', {
          ...this.info,
          photo: res.data.data.photo
        })

        // 隐藏裁剪容器区域
        this.cropShow = false
      });
    },
  },

  created() {
    this.$store.dispatch("reqUserInfo");
  },

  // 简化访问vuex，也写一个计算属性
  computed: {
    // 相当于就是给state里的userInfo起了一个别名叫info
    info() {
      return this.$store.state.userInfo;
    },
  },
};
</script>

<style scoped lang="less">
// 头像div
.avatar-box {
  height: 140px;
  display: flex;
  // 设置主轴居中和副轴居中就能水平垂直都居中了
  justify-content: center;
  align-items: center;
  position: relative;

  .avatar {
    width: 120px;
    height: 120px;
  }

  .pic-uploader {
    position: absolute;
    width: 100%;
    height: 100%;

    ::v-deep {
      .van-uploader__wrapper {
        height: 100%;

        .van-uploader__upload {
          width: 100%;
          height: 100%;
          // 因为还需要它点击右反应
          // 因此，要用opacity
          opacity: 0;
        }
      }
    }
  }
}

.nameField {
  border: 1px solid #ddd;
}

.pop {
  height: 130px;
}

.popBirth {
  height: 220px;
}

.crop-box {
  // 使用固定定位，那么此时参照的是文档（显示区域）
  position: fixed;
  width: 100%;
  height: 100%;
  left: 0;
  top: 0;
  background-color: #f00;

  .van-button {
    position: absolute;
    bottom: 0;
    left: 0;

    // 找到第二个按钮
    // 不能用nth-child（必须保证在父盒子中也是第几个子元素）
    &:nth-of-type(2) {
      // 让left恢复默认值
      left: auto;
      right: 0;
    }
  }
}
</style>